import base64
from flask import Flask, request
import json
import numpy as np
from standardization_experiment import normalize

from train_feature import train
from standardization_norml import standardize
from thruster_predict import predict
from thruster_feature_extraction import feature_extract

from envelope import LocalOutlierFactorTest_2D, OneclassSVMTest_2D, FeatureBaggingTest_2D
import matplotlib.pyplot as plt
import dimensionality_reduction1

app = Flask(__name__)
global index_name


# 将图片文件转码成文件流，便于前端传输
def return_img_stream(img_local_path):
    img_stream = ''
    with open(img_local_path, 'rb') as img_f:  # 'rb' 允许打开二进制的图片
        img_stream = img_f.read()
        img_stream = base64.b64encode(img_stream)
    return img_stream


# 模型预测处理前图像
@app.route('/pre_handle_func', methods=['POST'])
def pre_handle_func():
    value = json.loads(request.data)[0]
    img_path = './img/normal' + value + ".png"
    return return_img_stream(img_path)


# 模型预测处理后图像
@app.route('/post_handle_func', methods=['POST'])
def post_handle_func():
    value = json.loads(request.data)[0]
    img_path = "./img/standardization_normal" + value + ".png"
    return return_img_stream(img_path)


# 模型训练处理前图像
@app.route('/pre_treat_func', methods=['POST'])
def pre_treat_func():
    value = json.loads(request.data)[0]
    img_path = "./img/experiment" + value + ".png"
    img_stream = return_img_stream(img_path)
    return img_stream


# 模型训练处理后图像
@app.route('/post_treat_func', methods=['POST'])
def post_treat_func():
    value = json.loads(request.data)[0]
    img_path = "./img/standardization_experiment" + value + ".png"
    img_stream = return_img_stream(img_path)
    return img_stream


# 预测函数
@app.route('/predict', methods=['POST'])
def predict_func():
    model = json.loads(request.data)[0]
    model_path = "./model/" + model
    predict(model_path, index_name)

    value = "1"
    img_path = "./img/predict_res" + value + ".png"
    img_stream = return_img_stream(img_path)

    return img_stream


@app.route('/selection', methods=['POST'])
def selection_func():
    value = json.loads(request.data)[0]
    img_path = "./img/predict_res" + value + ".png"
    return return_img_stream(img_path)


# 模型预测标准化算法
@app.route('/standardize', methods=['POST'])
def stand_func():
    data_path = json.loads(request.data)[0]
    index = standardize(data_path)
    return {"res": index}


# 模型训练算法
@app.route('/train', methods=['POST'])
def train_func():
    data = json.loads(request.data)
    learn_rate = float(data[0])
    unit_num = int(data[1])
    activate_func = data[2]
    loss_func = data[3]

    train(learn_rate, unit_num, activate_func, loss_func)

    img_path = "./img/loss.png"
    img_stream = return_img_stream(img_path)

    return img_stream


# 模型训练标准化算法
@app.route('/normalize', methods=['POST'])
def nomalize_func():
    content = json.loads(request.data)[0]
    datapath = "./testdata/" + content
    index = normalize(datapath)
    global index_name
    index_name = index
    print(type(index))
    return {"res": index}


# # 特征提取方法
# @app.route('/extract',methods=["POST", "GET"])
# def extract_func():
#     if request.method == 'POST':
#         content = json.loads(request.data)
#         data_path = experiment.transform(content[0])
#         result = dimensionality_reduction.reducer(data_path, content[2])
#         return {"res":result[0].tolist()}
#     return 'extract_func'


# 特征提取，所有特征都做
@app.route('/post_hl_d', methods=["POST"])
def post_hl_d():
    item = json.loads(request.data)[0]
    if item == "high":
        img_path = "./img/high_feature1.png"
    else:
        img_path = "./img/low_feature1.png"
    feature_extract()
    return return_img_stream(img_path)


# 获取单一特征图片
@app.route('/submit2', methods=['POST'])
def submit2_func():
    item = json.loads(request.data)[0]
    value = json.loads(request.data)[1]
    # dimension = json.loads(request.data)[2]

    if item == "high":
        img_path = "./img/high_feature" + value + ".png"
    else:
        img_path = "./img/low_feature" + value + ".png"

    return return_img_stream(img_path)


# 特征降维
@app.route('/post_reduc', methods=["POST"])
def post_reduc():
    # //接收high或low,维度两个参数。调用高低温数据提取的函数
    if request.method == 'POST':
        # 高低温
        para1 = json.loads(request.data)["p1"]
        # 维度
        para2 = json.loads(request.data)["p2"]
        # 降维方法
        para3 = json.loads(request.data)["p3"][0]
        print("para1:" + para1)
        print("para2:" + para2)
        print("para3:" + para3)

        reduction, score = dimensionality_reduction1.reducer(temperature=para1, feature=para2, option=para3)

        score_np = np.array(score)
        np.save("./predict_result/score.npy", score_np)

        plt.figure(figsize=(20, 16), dpi=80)
        plt.tick_params(labelsize=40)
        # 二维和一维图像
        if reduction.shape[1] == 1:
            index = np.arange(1, 1 + reduction.shape[0]).reshape(-1, 1)
            reduction = np.concatenate((index, reduction), axis=1)
            plt.scatter(reduction[:, 0], reduction[:, 1], s=1000)
            plt.xlabel(u'产品编号', fontproperties='Microsoft YaHei', fontsize=40)
            plt.ylabel(u'特征值', fontproperties='Microsoft YaHei', fontsize=40)
            plt.title(u'不降维展示', fontproperties='Microsoft YaHei', fontsize=40)
        else:
            plt.scatter(reduction[:, 0], reduction[:, 1], s=1000)
            plt.xlabel(u'特征值1', fontproperties='Microsoft YaHei', fontsize=40)
            plt.ylabel(u'特征值2', fontproperties='Microsoft YaHei', fontsize=40)
            plt.title(u'降维展示', fontproperties='Microsoft YaHei', fontsize=40)

        plt.tight_layout()
        plt.savefig("./img/reduction_feature.png")
        # plt.show()
        plt.close()
        np.save('./predict_result/reduction_features.npy', reduction)
        # h1图片路径
        file_path = "./img/reduction_feature.png"
        resp = return_img_stream(file_path)
        return resp


@app.route('/score', methods=['POST'])
def post_func():
    score = np.load('./predict_result/score.npy')
    return {"res": score.tolist()}


# 包络绘制
@app.route('/post', methods=["POST"])
def hello_post():
    if request.method == 'POST':
        algorithm = json.loads(request.data)["algorithm"]
        para1 = json.loads(request.data)["p1"]
        para2 = json.loads(request.data)["p2"]
        plt.rcParams['font.sans-serif'] = ['SimHei']
        plt.rcParams['axes.unicode_minus'] = False
        feature_ = np.load('./predict_result/reduction_features.npy')
        if algorithm[0] == 'LOF':
            product_id = LocalOutlierFactorTest_2D(feature_, int(para1), float(para2))
            file_path = './img/LOF.png'
        else:
            product_id = OneclassSVMTest_2D(feature_, int(para1), float(para2))
            file_path = './img/OneclassSVM_2D.png'
        global product
        product = str(product_id)
        resp = return_img_stream(file_path)

    return resp


# 包络融合
@app.route('/post_mix', methods=["POST"])
def post_mix():
    # //接收high或low,维度两个参数。调用高低温数据提取的函数
    if request.method == 'POST':
        feature_ = np.load('./predict_result/reduction_features.npy')
        # 权重1
        para1 = json.loads(request.data)["p1"]
        # 权重2
        para2 = json.loads(request.data)["p2"]
        # print(type(para1))
        para1 = float(para1)
        para2 = float(para2)
        # print(type(para1))
        plt.rcParams['font.sans-serif'] = ['SimHei']
        plt.rcParams['axes.unicode_minus'] = False
        product_id = FeatureBaggingTest_2D(feature_, float(para1), float(para2))
        file_path = './img/FeatureBagging.png'
        global product
        product = str(product_id)
        print(product)
        resp = return_img_stream(file_path)

    return resp


# 包络融合决策
@app.route('/decision', methods=["POST"])
def decision():
    print(product)
    return product


if __name__ == '__main__':
    app.run(host='localhost', port=8010, debug=True)
